WITH Ada.Text_Io;
USE Ada.Text_Io;
PACKAGE BODY Linked_List IS

   ------------------
   -- delete_after --
   ------------------

   FUNCTION Delete_After (
         Head_Link : Link_A)
     RETURN Link_A IS
      Tmp : Link_A;
   BEGIN
      if head_link.next /= null then
	Tmp := Head_Link.Next;
	Head_Link.Next := Head_Link.Next.Next;
        free(tmp);
      end if;
      RETURN Head_Link;
   END Delete_After;

   ------------------
   -- delete_first --
   ------------------

   FUNCTION Delete_First (
         A_List : List_A)
     RETURN Link_A IS
      Tmp : Link_A;
   BEGIN
      IF A_List.Head /= NULL THEN
         Tmp := A_List.Head;
         A_List.Head := Tmp.Next;
         free(tmp);
      END IF;
      RETURN A_List.Head;
   END Delete_First;

   function delete_last ( a_list : list_a) return link_a is
	last_link, prev_link : link_a;
   begin
	last_link := a_list.head;
	while last_link.next /= null loop
	    prev_link := last_link;
	    last_link := last_link.next;
	end loop;
	prev_link.next := null;
	free(last_link);
	return prev_link;
    end delete_last;


   ------------------
   -- insert_after --
   ------------------

   FUNCTION Insert_After (
         Head_Link : Link_A;
         N_Link    : Link_A)
     RETURN Link_A IS
      Tmp : Link_A;
   BEGIN
      Tmp := Head_Link.Next;
      Head_Link.Next := N_Link;
      N_Link.Next := Tmp;
      RETURN N_Link;
   END Insert_After;

   ------------------
   -- insert_after --
   ------------------

   FUNCTION Insert_After (
         Head_Link : Link_A;
         Data      : item)
     RETURN Link_A IS
      Tmp,
      N_Link : Link_A;
   BEGIN
      Tmp := Head_Link.Next;
      N_Link := NEW Link'(
         Next => Tmp,
         Data => Data);
      Head_Link.Next := N_Link;
      RETURN N_Link;
   END Insert_After;

   ------------------
   -- insert_first --
   ------------------

   FUNCTION Insert_First (
         A_List : List_A;
         N_Link : Link_A)
     RETURN Link_A IS
   BEGIN
      N_Link.Next := A_List.Head;
      A_List.Head := N_Link;
      RETURN A_List.Head;
   END Insert_First;

   ------------------
   -- insert_first --
   ------------------

   FUNCTION Insert_First (
         A_List : List_A;
         Data   : item)
     RETURN Link_A IS
      N_Link : Link_A;
   BEGIN
      N_Link := NEW Link'(
         Next => A_List.Head,
         Data => Data);
      A_List.Head := N_Link;
      RETURN A_List.Head;
   END Insert_First;

   --------------
   -- new_list --
   --------------

   FUNCTION New_List RETURN List_A IS
      A_List    : List_A;
   BEGIN
      a_list := new list'(head => NULL);
      RETURN A_List;
   END New_List;

   ----------------
   -- print_list --
   ----------------

   PROCEDURE Print_List (
         A_List : IN     List_A) IS
      N_Link : Link_A;
   BEGIN
      N_Link := A_List.Head;
      LOOP
         print(n_link.data);
         N_Link := N_Link.Next;
         EXIT WHEN N_Link = NULL;
      END LOOP;
   END Print_List;

END Linked_List;

